package com.scalar.chiptrack.adaptor.grace;

import com.scalar.chiptrack.jobs.JobHandler;
import com.scalar.chiptrack.adaptor.AdaptorConstants;
import com.scalar.chiptrack.adaptor.AdaptorUtils;
import com.scalar.chiptrack.adaptor.ParserException;
import com.scalar.chiptrack.adaptor.FabSortLot;
import com.scalar.chiptrack.adaptor.ShippedLot;
import com.scalar.chiptrack.adaptor.dao.FabSortAdaptorDAO;
import com.scalar.chiptrack.adaptor.dao.ShippedLotDAO;
import com.scalar.chiptrack.adaptor.dao.AdaptorDAO;
import com.scalar.chiptrack.adaptor.dao.AdaptorRunInfo;
import com.scalar.chiptrack.utils.Logger;
import com.scalar.chiptrack.utils.StringUtils;
import com.scalar.ScalarException;

import java.util.HashMap;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

/**
 * Created by IntelliJ IDEA.
 * User: Sudhakar
 * Date: May 1, 2007
 * Time: 2:35:33 PM
 */
public class GraceDataParser extends JobHandler implements AdaptorConstants
{
    private static Logger m_parserLogger    = null;
    private String m_dataOutputDir          = null;
    private HashMap m_wipDataMap            = new HashMap();
    private HashMap m_shipDataMap           = new HashMap();

    public GraceDataParser() throws ScalarException
    {
        try
        {
            m_dataOutputDir = AdaptorUtils.getDataOutputDir(VENDOR_NAME_GRACE, WIP_TYPE_FAB);
            AdaptorUtils.makeAllAdaptorDirs( m_dataOutputDir );

            m_parserLogger = AdaptorUtils.getDataParserLogger( m_dataOutputDir, VENDOR_NAME_GRACE );
            FabSortAdaptorDAO.setLogger(m_parserLogger);   // All the DAOs and Parser should be logging into same file
            ShippedLotDAO.setLogger(m_parserLogger);
            AdaptorUtils.setLogger( m_parserLogger);
        }
        catch (ScalarException se)
        {
            log("ERROR!! ERROR!! ERROR!! Exception while loading Grace WIP output directory details from database, Exception: " + se);
            throw se;
        }
    }
    /**
     *
     * @param args
     * @throws Exception
     */
    public static void main(String args[]) throws Exception
    {
        new GraceDataParser().execute();
    }
    /**
     *
     * @throws Exception
     */
    public void execute() throws Exception
    {
        AdaptorUtils.printHeader(VENDOR_NAME_GRACE, CONSTANT_PARSER);

        File doneDestDir = new File( m_dataOutputDir + "/done" );

        File graceWipDataoutDir = new File(m_dataOutputDir);
                
        File[] fileList = graceWipDataoutDir.listFiles();

        if ((fileList == null) || (fileList.length <= 3))
        {
            log("No file found in directory: " + graceWipDataoutDir);
            throw new ScalarException("No file found in directory: " + graceWipDataoutDir + "----\n\n");
        }
                
        ArrayList successFileList   = new ArrayList();
        boolean success             = true;

        try
        {
            for (int i = 0; i < fileList.length; i++)
            {
                if (fileList[i].isDirectory() == true)
                {
                    continue;
                }


                if (fileList[i].getName() != null && fileList[i].getName().trim().startsWith(GraceAdaptor.WIP_INFO_FILE_NAME) )
                {
                    try
                    {
                        ArrayList m_graceWipList = parseWipInfo(fileList[i].getAbsolutePath());

                        if (m_graceWipList != null && m_graceWipList.size() > 0 )
                        {
                            getGraceWipList(m_graceWipList);
                        }
                        successFileList.add(fileList[i]);
                    }
                    catch (Exception e)
                    {
                        success = false;
                        log("Exception while parsing and storing file: " + fileList[i].getAbsolutePath() + "\nException: " + e);
                        e.printStackTrace();
                        throw e;
                    }
                }

                if (fileList[i].getName() != null && fileList[i].getName().trim().startsWith(GraceAdaptor.SHIPPING_FILE_NAME) )
                {
                    try
                    {
                        ArrayList m_graceShipList = parseShippingInfo(fileList[i].getAbsolutePath());

                        if (m_graceShipList != null && m_graceShipList.size() > 0 )
                        {
                            getGraceShipList(m_graceShipList);
                        }

                        successFileList.add(fileList[i]);
                    }
                    catch (Exception e)
                    {
                        success = false;
                        log("Exception while parsing and storing file: " + fileList[i].getAbsolutePath() + "\nException: " + e);
                        e.printStackTrace();
                        throw e;
                    }
                }
            }
        }
        catch (Exception e)
        {
            success = false;
            log("ERROR!! ERROR!! ERROR!! While parsing and storing File " + e);
            e.printStackTrace();
            throw e;
        }
        // to save the Fab lot tables
        try
        {
            if (m_wipDataMap.isEmpty() == false)
            {
                log("Updating Fab Lot Information");
                FabSortAdaptorDAO.saveFabLot(null, m_wipDataMap.values().iterator(), WIP_TYPE_FAB, VENDOR_NAME_GRACE);
            }
            else
            {
                System.out.println("This is FAB Data Parser FAB Part Number List is empty");
                FabSortAdaptorDAO.closeFabSortLot(null, WIP_TYPE_FAB, VENDOR_NAME_GRACE);
            }
        }
        catch (Exception e)
        {
            success = false;
            log("ERROR!! ERROR!! ERROR!! Could not update Fab Data information into database: " + e);
            e.printStackTrace();
            throw e;
        }

        try
        {
            // Save shipping info -
            if (m_shipDataMap.isEmpty() == false)
            {
                log("Updating shipment Information");
                ShippedLotDAO.saveShippedLot(null, m_shipDataMap.values().iterator());
            }
        }
        catch (Exception e)
        {
            success = false;
            log("ERROR!! ERROR!! ERROR!! Could not update Grace Shipping information into database: " + e);
            e.printStackTrace();
            throw e;
        }

        // TO SEND THE NEW LOTS, NEW TRANSIT LOTS, NO PO LOTS, DISCREPANCY LOTS NOTIFICATIONS TO THE USER
        AdaptorDAO.sendAllNotifications(VENDOR_NAME_GRACE, true, true, true);

        // To Close the Drop Out Lots
        AdaptorDAO.closeDropOutLots(VENDOR_NAME_GRACE);

        int adaptor_id = AdaptorRunInfo.getLastRunAdaptorId( GraceAdaptor.ADAPTOR_NAME, CONSTANT_ADAPTOR);

        // Update Adaptor_Run_Info table
        try
        {
            if ( success == true )
            {
                AdaptorRunInfo.saveAdaptorLastUpdatedStatus(CONSTANT_PARSER, GraceAdaptor.ADAPTOR_NAME, CONSTANT_SUCCESS, adaptor_id);
                System.out.println( "SUCCESSFULLY UPDATED IN THE DATABASE" );
            }
        }
        catch ( ScalarException se )
        {
            success = false; //As filES DATA SAVED , UPDATEING AS SUCCESS
            AdaptorRunInfo.saveAdaptorLastUpdatedStatus(CONSTANT_PARSER, GraceAdaptor.ADAPTOR_NAME, CONSTANT_SUCCESS, adaptor_id);
            log( "WARNING!! WARNING!! WARNING!! Could not update Adaptor run information, Exception: " + se );
            throw se;
        }
        
       // Move the successful files to 'done' directory
       if ( success )
       {
           AdaptorUtils.moveFilesToDone( successFileList, doneDestDir );
       }
    }
    /**
     *
     * @param fileName
     * @return
     * @throws Exception
     */
    private ArrayList parseWipInfo(String fileName) throws Exception
    {
        if (fileName == null) throw new ScalarException("Filename argument is null");

        ArrayList wipInfoList       = new ArrayList();
        BufferedReader fileReader   = null;

        try
        {
            File wipInfoFile = new File(fileName);
            if (wipInfoFile.exists() == false)
            {
                throw new ScalarException(fileName + " doesnt exist");
            }

            System.out.println("Found " + fileName);
            System.out.println("Parsing the file for Wip Information...");

            fileReader = new BufferedReader(new FileReader(wipInfoFile));

            String line             = null;
            GraceWipStatus wipInfo  = null;
            ArrayList errors        = new ArrayList();

            fileReader.readLine();  // skip 1st line

            while ((line = fileReader.readLine()) != null)
            {
                try
                {
                    wipInfo = parseWipInfoLine(line);
                }
                catch (ParserException pe)
                {
                    wipInfo = null;
                    errors.add(pe.getMessage());
                }
                if (wipInfo != null)
                {
                    wipInfoList.add(wipInfo);
                }
            }

            fileReader.close();
            fileReader = null;

            System.out.println("Done parsing..");

            if (errors.isEmpty() == false)
            {
                System.out.println("\nFound errors... notifying system administrator...");
                System.out.println("done\n");
            }
        }
        finally
        {
            if (fileReader != null)
            {
                try
                {
                    fileReader.close();
                }
                catch (IOException ignore) {
                }
            }
        }
        return wipInfoList;
    }
    /**
     *
     * @param line
     * @return
     * @throws ParserException
     */
    private GraceWipStatus parseWipInfoLine(String line) throws ParserException
    {
        GraceWipStatus wipInfo = null;

        if ((line == null) || (line.startsWith("---")) || (line.trim().length() < 65 /*min length*/))
        {
            return wipInfo;
        }

        try
        {
            line = line.replaceAll( "\"", " " ); // if remove hear it throws exception.
            String[] token = line.split(",");

            wipInfo = new GraceWipStatus();

            for (int x = 0; x < token.length; x++)
            {
                if (token[x] != null && token[x].trim().length() > 0)
                {
                    switch (x)
                    {
                        case 0:
                            wipInfo.setLotId(token[x].trim());
                            break;
                        case 1:
                            wipInfo.setProduct(token[x].trim());
                            break;
                        case 2:
                            wipInfo.setStage(token[x].trim());
                            break;
                        case 3:
                            wipInfo.setLotStatus(token[x].trim());
                            break;
                        case 4:
                            wipInfo.setLotType(token[x].trim());
                            break;
                        case 5:
                            wipInfo.setwQty(token[x].trim());
                            break;
                        case 6:
                            wipInfo.setWsQty(token[x].trim());
                            break;
                        case 7:
                            wipInfo.setWsDate(token[x].trim());
                            break;
                        case 8:
                            wipInfo.setJobinTime(token[x].trim());
                            break;
                        case 9:
                            wipInfo.setPlanComplete(token[x].trim());
                            break;
                        case 10:
                            wipInfo.setCustCompleteDate(token[x].trim());
                            break;
                        case 11:
                            wipInfo.setForcastFabOut(token[x].trim());
                            break;
                        case 12:
                            wipInfo.setCustId(token[x].trim());
                            break;
                        case 13:
                            wipInfo.setFabId(token[x].trim());
                            break;
                        case 14:
                            wipInfo.setCustPO(token[x].trim());
                            break;
                        case 15:
                            wipInfo.setCustProd(token[x].trim());
                            break;
                        case 16:
                            wipInfo.setLotPriority(token[x].trim());
                            break;
                        case 17:
                            wipInfo.setLayerSeq(token[x].trim());
                            break;
                        case 18:
                            wipInfo.setTotalLayer(token[x].trim());
                            break;
                        case 19:
                            wipInfo.setRate(token[x].trim());
                            break;
                        case 20:
                            wipInfo.setDelayDate(token[x].trim());
                            break;
                        //case 21
                        case 22:
                            wipInfo.setStayDate(token[x].trim());
                            break;
                        case 23:
                            wipInfo.setGrossDie(token[x].trim());
                            break;
                        //24,25
                        case 26:
                            wipInfo.setWaferId(token[x].trim());
                            break;
                    }
                }
            }
        }
        catch (Exception e)
        {
            System.out.println("Exception while parsing Wip Info: " + e);
            System.out.println("Line: " + line);
            throw new ParserException("Exception while parsing Wip Info: " + e + "\nLine: " + line, e);
        }

        return wipInfo;
    }

    /**
     *
     * @param wipdataList
     */
    public void getGraceWipList(ArrayList wipdataList)
    {
        GraceWipStatus graceWipReport   = null;
        String partNumber               = null;
        String lotNumber                = null;
        FabSortLot fabSortLot           = null;

        Iterator iterator = wipdataList.iterator();
        while ( iterator.hasNext() )
        {
            graceWipReport = (GraceWipStatus) iterator.next();

            if (graceWipReport != null )
            {
                partNumber  = graceWipReport.getProduct();
                lotNumber   = graceWipReport.getLotId();

                int wquantity = 0;
                try
                {
                    if (graceWipReport.getLotStatus() != null && graceWipReport.getLotStatus().trim().equalsIgnoreCase("SCHEDULE") )
                    {
                        wquantity += Integer.parseInt( graceWipReport.getWsQty() );
                    }
                    else
                    {
                        wquantity += Integer.parseInt( graceWipReport.getwQty() );
                    }
                }
                catch (NumberFormatException ignore)
                {
                      wquantity = 0;
                }
                if ( partNumber != null && lotNumber != null )
                {
                    fabSortLot = (FabSortLot) m_wipDataMap.get(partNumber + lotNumber);
                    if (fabSortLot == null)
                    {
                        fabSortLot = new FabSortLot( VENDOR_NAME_GRACE, WIP_TYPE_FAB );
                        m_wipDataMap.put(partNumber + lotNumber, fabSortLot);
                    }
                    int quantity = 0;

                    if (fabSortLot.getQtyIn() != null)
                    {
                        try
                        {
                            quantity = Integer.parseInt( fabSortLot.getQtyIn());
                        }
                        catch (NumberFormatException ignore) {
                        }

                        quantity += wquantity;
                    }
                    else
                    {
                        quantity = wquantity;
                    }

                    if ( quantity > 0 )
                    {
                        fabSortLot.setLotId(lotNumber);
                        fabSortLot.setCustProduct(partNumber);
                        fabSortLot.setDateIn(StringUtils.formatDate(graceWipReport.getWsDate(), "yyyy-MM-dd hh:mm:ss", "MM/dd/yyyy"));
                        fabSortLot.setDateOut(StringUtils.formatDate(graceWipReport.getCustCompleteDate(), "yyyy-MM-dd hh:mm:ss", "MM/dd/yyyy"));
                        fabSortLot.setOutLookDate(StringUtils.formatDate(graceWipReport.getPlanComplete(), "yyyy-MM-dd hh:mm:ss", "MM/dd/yyyy"));
                        fabSortLot.setForcastedDateOut(StringUtils.formatDate(graceWipReport.getForcastFabOut(), "yyyy-MM-dd hh:mm:ss", "MM/dd/yyyy"));
                        fabSortLot.setQtyIn(quantity + "");
                        fabSortLot.setStage( graceWipReport.getStage() );
                        fabSortLot.setFabLotNumber(lotNumber);
                        fabSortLot.setFabId( graceWipReport.getFabId() );
                        if (graceWipReport.getLotStatus() != null && graceWipReport.getLotStatus().equalsIgnoreCase("WAIT") )
                        {
                            fabSortLot.setLotStatus(LOT_STATUS_HOLD);
                        }
                        else
                        {
                            fabSortLot.setLotStatus(LOT_STATUS_RUNNING);
                        }
                        fabSortLot.setPoNumber(graceWipReport.getCustPO());
                    }
                }
            }
        }
    }
    /**
     *
     * @param fileName
     * @return
     * @throws Exception
     */
    private ArrayList parseShippingInfo(String fileName) throws Exception
    {
        if (fileName == null) throw new ScalarException("Filename argument is null");

        ArrayList shippingInfoList  = new ArrayList();
        BufferedReader fileReader   = null;

        try
        {
            File shippingInfoFile = new File(fileName);
            if (shippingInfoFile.exists() == false)
            {
                throw new ScalarException(fileName + " doesnt exist");
            }

            System.out.println("Found " + fileName);
            System.out.println("Parsing the file for Shipping Information...");

            fileReader = new BufferedReader(new FileReader(shippingInfoFile));

            String line                     = null;
            GraceShipStatus shippingInfo    = null;
            ArrayList errors                = new ArrayList();

            fileReader.readLine();  // skip 1st line

            while ((line = fileReader.readLine()) != null)
            {
                try
                {
                    shippingInfo = parseShippingInfoLine(line);
                }
                catch (ParserException pe)
                {
                    shippingInfo = null;
                    errors.add(pe.getMessage());
                }

                if (shippingInfo != null)
                {
                    shippingInfoList.add(shippingInfo);
                }
            }

            fileReader.close();
            fileReader = null;

            System.out.println("Done parsing..");

            if (errors.isEmpty() == false)
            {
                System.out.println("\nFound errors... notifying system administrator...");
                System.out.println("done\n");
            }
        }
        finally
        {
            if (fileReader != null)
            {
                try
                {
                    fileReader.close();
                }
                catch (IOException ignore) {
                }
            }
        }

        return shippingInfoList;
    }

    /**
     *
     * @param line
     * @return
     * @throws ParserException
     */
    private GraceShipStatus parseShippingInfoLine(String line) throws ParserException
    {

        GraceShipStatus shippingInfo = null;

        if ((line == null) || (line.startsWith("---")) || (line.trim().length() < 70 /*min length*/))
        {
            return shippingInfo;
        }


        try
        {
            line = line.replaceAll( "\"", " " ); // if remove hear it throws exception.
            String[] token = line.split(",");
            shippingInfo = new GraceShipStatus();

            for (int x = 0; x < token.length; x++)
            {
                if (token[x] != null && token[x].trim().length() > 0)
                {
                    switch (x)
                    {
                        case 0:
                            shippingInfo.setCustomerSO(token[x].trim());
                            break;
                        case 1:
                            shippingInfo.setSoItemNo(token[x].trim());
                            break;
                        case 2:
                            shippingInfo.setCustPO(token[x].trim());
                            break;
                        case 3:
                            shippingInfo.setPoDate(token[x].trim());
                            break;
                        case 4:
                            shippingInfo.setInvoiceNo(token[x].trim());
                            break;
                        case 5:
                            shippingInfo.setCustProduct(token[x].trim());
                            break;
                        case 6:
                            shippingInfo.setLotNo(token[x].trim());
                            break;
                        case 7:
                            shippingInfo.setProduct(token[x].trim());
                            break;
                        case 8:
                            shippingInfo.setShipQty(token[x].trim());
                            break;
                        case 9:
                            shippingInfo.setInvoiceQty(token[x].trim());
                            break;
                        case 10:
                            shippingInfo.setUnit(token[x].trim());
                            break;
                        case 11:
                            shippingInfo.setWsDate(token[x].trim());
                            break;
                        case 12:
                            shippingInfo.setEtaDate(token[x].trim());
                            break;
                        case 13:
                            shippingInfo.setActualFabOut(token[x].trim());
                            break;
                        case 14:
                            shippingInfo.setShipDate(token[x].trim());
                            break;
                        case 15:
                            shippingInfo.setTrackingNumber(token[x].trim());
                            break;
                        case 16:
                            shippingInfo.setHawbNumber(token[x].trim());
                            break;
                        case 17:
                            shippingInfo.setMawbNumber(token[x].trim());
                            break;
                        case 18:
                            shippingInfo.setFltDate(token[x].trim());
                            break;
                        case 19:
                            shippingInfo.setCustId(token[x].trim());
                            break;
                        case 20:
                            shippingInfo.setShipTo(token[x].trim());
                            break;
                        case 21:
                            shippingInfo.setWaferId(token[x].trim());
                            break;
                    }
                }
            }

        }
        catch (Exception e)
        {
            System.out.println("Exception while parsing Shipping Info: " + e);
            System.out.println("Line: " + line);
            throw new ParserException("Exception while parsing Shipping Info: " + e + "\nLine: " + line, e);
        }

        return shippingInfo;
    }

    /**
     *
     * @param shipdataList
     */
    private void getGraceShipList(ArrayList shipdataList)
    {
        GraceShipStatus graceShipReport = null;
        ShippedLot shippedLot           = null;
        String partNumber               = null;
        String lotNumber                = null;
        String invoiceNo                = null;
        String shipDate                 = null;
        String nextLocation             = null;
        Iterator iterator = shipdataList.iterator();

        while (iterator.hasNext())
        {
            graceShipReport = (GraceShipStatus) iterator.next();

            partNumber  = graceShipReport.getCustProduct();
            lotNumber   = graceShipReport.getLotNo();
            shipDate    = graceShipReport.getShipDate();
            nextLocation = graceShipReport.getShipTo();

            if (graceShipReport != null && partNumber != null && lotNumber != null  && graceShipReport.getShipQty() != null
                    && graceShipReport.getShipQty().trim().length() > 0)
            {

                shippedLot = (ShippedLot) m_shipDataMap.get(lotNumber + partNumber + invoiceNo + shipDate + nextLocation );

                if (shippedLot == null)
                {
                    shippedLot = new ShippedLot(VENDOR_NAME_GRACE, LOCATION_TYPE_FAB);
                    m_shipDataMap.put(lotNumber + partNumber + invoiceNo + shipDate+nextLocation, shippedLot);
                }
                int quantity = 0;
                if (shippedLot.getShipQty() != null)
                {
                    try
                    {
                        quantity = Integer.parseInt(shippedLot.getShipQty());
                    }
                    catch (NumberFormatException ignore) {
                    }
                    try
                    {
                        quantity += Integer.parseInt(graceShipReport.getShipQty());
                    }
                    catch (NumberFormatException ignore) {
                    }
                }
                else
                {
                    try
                    {
                        quantity = Integer.parseInt(graceShipReport.getShipQty());
                    }
                    catch (NumberFormatException ignore) {
                    }
                }

                if ( quantity > 0)
                {
                    shippedLot.setLotNumber(lotNumber);
                    shippedLot.setPartNumber(partNumber);
                    shippedLot.setShipDate(StringUtils.formatDate(shipDate, "yyyy-MM-dd hh:mm:ss", "MM/dd/yyyy"));
                    shippedLot.setShipQty(quantity + "");
                    shippedLot.setCustomerPO(graceShipReport.getCustPO());
                    shippedLot.setCustomerSO(graceShipReport.getCustomerSO());
                    shippedLot.setNextLocation(nextLocation);
                    shippedLot.setFabLotNumber(lotNumber);
                    shippedLot.setEta(StringUtils.formatDate(graceShipReport.getEtaDate(), "yyyy-MM-dd hh:mm:ss", "MM/dd/yyyy"));
                    shippedLot.setHawb(graceShipReport.getHawbNumber());
                    shippedLot.setMawb(graceShipReport.getMawbNumber());
                    shippedLot.setWaferID( graceShipReport.getWaferId());
                    shippedLot.setInvoiceNumber( graceShipReport.getInvoiceNo() );
                }
            }
        }
    }
    /**
     *
     * @param message
     */
    private static void log(String message)
    {
        if (message == null) return;

        if (m_parserLogger != null)
        {
            synchronized (m_parserLogger)
            {
                m_parserLogger.logDebug(message + LINE_SEPARATOR);
            }
        }
        else
        {
            System.out.println(message);
        }
    }
    /**
     *
     */
    private void printVersionInfo()
    {
        String info = "\n\n+----------- Running Grace FAB Data Parser on " + new java.util.Date(System.currentTimeMillis()) + " -------------+\n" +
                "\n+---------------------------------------------------------------+\n" +
                "+                                                                \n" +
                "+            Grace FAB Data Interpreter - Beta          \n" +
                "+                                                                \n" +
                "+    Copy Right (C) 2007 - ScalarSoft Inc., All rights reserved.  \n" +
                "+                                                                \n" +
                "+---------------------------------------------------------------+\n";
        System.out.println(info);
        log(info);
    }

}
